#include "LuaTableWrapper.h"
#include <iostream>

/**
 * @brief 构造函数，初始化Lua表封装对象
 */
LuaTableWrapper::LuaTableWrapper() {}

/**
 * @brief 析构函数，清理资源
 */
LuaTableWrapper::~LuaTableWrapper() {}

/**
 * @brief 设置字符串键对应的值
 * @param key 字符串键
 * @param value 要设置的值，可以是多种类型
 */
void LuaTableWrapper::set(const std::string& key, const std::any& value) {
    string_keys[key] = value;
}

/**
 * @brief 设置整数键对应的值
 * @param key 整数键
 * @param value 要设置的值，可以是多种类型
 */
void LuaTableWrapper::set(int key, const std::any& value) {
    int_keys[key] = value;
}

/**
 * @brief 获取字符串键对应的值
 * @param key 字符串键
 * @return 返回存储的值，如果不存在返回空any
 */
std::any LuaTableWrapper::get(const std::string& key) const {
    auto it = string_keys.find(key);
    if (it != string_keys.end()) {
        return it->second;
    }
    return std::any();
}

/**
 * @brief 获取整数键对应的值
 * @param key 整数键
 * @return 返回存储的值，如果不存在返回空any
 */
std::any LuaTableWrapper::get(int key) const {
    auto it = int_keys.find(key);
    if (it != int_keys.end()) {
        return it->second;
    }
    return std::any();
}

/**
 * @brief 删除字符串键对应的值
 * @param key 要删除的字符串键
 */
void LuaTableWrapper::remove(const std::string& key) {
    string_keys.erase(key);
}

/**
 * @brief 删除整数键对应的值
 * @param key 要删除的整数键
 */
void LuaTableWrapper::remove(int key) {
    int_keys.erase(key);
}

/**
 * @brief 创建并返回一个新的嵌套表，关联到字符串键
 * @param key 字符串键
 * @return 返回新创建的嵌套表指针
 */
std::shared_ptr<LuaTableWrapper> LuaTableWrapper::create_table(const std::string& key) {
    auto table = std::make_shared<LuaTableWrapper>();
    string_keys[key] = table;
    nested_tables.push_back(table); // 缓存嵌套表以管理生命周期
    return table;
}

/**
 * @brief 创建并返回一个新的嵌套表，关联到整数键
 * @param key 整数键
 * @return 返回新创建的嵌套表指针
 */
std::shared_ptr<LuaTableWrapper> LuaTableWrapper::create_table(int key) {
    auto table = std::make_shared<LuaTableWrapper>();
    int_keys[key] = table;
    nested_tables.push_back(table); // 缓存嵌套表以管理生命周期
    return table;
}

/**
 * @brief 清空表内容
 */
void LuaTableWrapper::clear() {
    string_keys.clear();
    int_keys.clear();
    nested_tables.clear();
}

/**
 * @brief Lua构造函数，创建新的LuaTableWrapper实例
 * @param L Lua状态机
 * @return 返回创建的实例数量(1)
 */
int LuaTableWrapper::lua_new(lua_State* L) {
    // 创建userdata存储指针
    void* ud = lua_newuserdata(L, sizeof(LuaTableWrapper*));
    LuaTableWrapper** wrapper = new (ud) LuaTableWrapper*;
    *wrapper = new LuaTableWrapper();
    
    // 设置元表
    luaL_getmetatable(L, "LuaTableWrapper");
    lua_setmetatable(L, -2);
    
    return 1;
}

/**
 * @brief Lua元方法__index实现，处理表访问操作
 * @param L Lua状态机
 * @return 返回访问结果数量(1)
 * 
 * 处理两种访问方式：
 * 1. 字符串键访问(table.key)
 * 2. 整数键访问(table[key])
 */
int LuaTableWrapper::lua_index(lua_State* L) {
    // 获取包装器实例
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    
    // 预定义类型检查函数，用于将C++值推入Lua栈
    auto push_value = [L](const std::any& value) {
        if (!value.has_value()) {
            lua_pushnil(L);
            return;
        }
        
        // 根据类型推入对应的Lua值
        if (value.type() == typeid(int)) {
            lua_pushinteger(L, std::any_cast<int>(value));
        } 
        else if (value.type() == typeid(double)) {
            lua_pushnumber(L, std::any_cast<double>(value));
        } 
        else if (value.type() == typeid(std::string)) {
            lua_pushstring(L, std::any_cast<std::string>(value).c_str());
        } 
        else if (value.type() == typeid(bool)) {
            lua_pushboolean(L, std::any_cast<bool>(value));
        } 
        else if (value.type() == typeid(std::shared_ptr<LuaTableWrapper>)) {
            // 处理嵌套表
            auto nested_table = std::any_cast<std::shared_ptr<LuaTableWrapper>>(value);
            void* ud = lua_newuserdata(L, sizeof(LuaTableWrapper*));
            LuaTableWrapper** ptr = new (ud) LuaTableWrapper*;
            *ptr = nested_table.get();
            luaL_getmetatable(L, "LuaTableWrapper");
            lua_setmetatable(L, -2);
        } 
        else {
            lua_pushnil(L);
        }
    };
    
    // 根据键类型处理访问
    if (lua_isstring(L, 2)) {
        const char* key = lua_tostring(L, 2);
        push_value(wrapper->get(key));
    } 
    else if (lua_isinteger(L, 2)) {
        int key = lua_tointeger(L, 2);
        push_value(wrapper->get(key));
    } 
    else {
        lua_pushnil(L);
    }
    
    return 1;
}

/**
 * @brief Lua元方法__newindex实现，处理表赋值操作
 * @param L Lua状态机
 * @return 返回结果数量(0)
 * 
 * 处理两种赋值方式：
 * 1. 字符串键赋值(table.key = value)
 * 2. 整数键赋值(table[key] = value)
 * 
 * 支持多种值类型：
 * - nil(删除键)
 * - 数字
 * - 字符串
 * - 布尔值
 * - 嵌套表
 */
// Lua __newindex元方法实现，处理表元素的赋值操作
int LuaTableWrapper::lua_newindex(lua_State* L) {
    // 从Lua栈获取包装器对象
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    
    // 处理表整体赋值 (t = {})
    // 特殊处理__self键的表整体赋值
    if (lua_isstring(L, 2) && strcmp(lua_tostring(L, 2), "__self") == 0 && lua_istable(L, 3)) {
        wrapper->clear();  // 清空现有内容
        
        // 遍历新表并复制所有键值对
        lua_pushnil(L);
        while (lua_next(L, 3) != 0) {
            if (lua_isinteger(L, -2)) {
                int key = lua_tointeger(L, -2);
                if (lua_isinteger(L, -1)) {
                    wrapper->set(key, std::any(lua_tointeger(L, -1)));
                } else if (lua_isnumber(L, -1)) {
                    wrapper->set(key, std::any(lua_tonumber(L, -1)));
                } else if (lua_isstring(L, -1)) {
                    wrapper->set(key, std::any(std::string(lua_tostring(L, -1))));
                } else if (lua_isboolean(L, -1)) {
                    wrapper->set(key, std::any(lua_toboolean(L, -1)));
                } else if (lua_istable(L, -1)) {
                    auto nested_table = std::make_shared<LuaTableWrapper>();
                    // 处理嵌套表...
                }
            } else if (lua_isstring(L, -2)) {
                const char* key = lua_tostring(L, -2);
                // 处理各种值类型...
            }
            lua_pop(L, 1);
        }
        return 0;
    }
    
    // 处理字符串键的赋值
    if (lua_isstring(L, 2)) {
        const char* key = lua_tostring(L, 2);
        
        if (lua_isnil(L, 3)) {
            // 删除指定键
            wrapper->remove(key);
        } else if (lua_isinteger(L, 3)) {
            // 设置整数值
            wrapper->set(key, std::any(lua_tointeger(L, 3)));
        } else if (lua_isnumber(L, 3)) {
            // 设置浮点数值
            wrapper->set(key, std::any(lua_tonumber(L, 3)));
        } else if (lua_isstring(L, 3)) {
            // 设置字符串值
            wrapper->set(key, std::any(std::string(lua_tostring(L, 3))));
        } else if (lua_isboolean(L, 3)) {
            // 设置布尔值
            wrapper->set(key, std::any(lua_toboolean(L, 3)));
        } else if (lua_istable(L, 3)) {
            // 处理嵌套表
            auto nested_table = std::make_shared<LuaTableWrapper>();
            
            // 遍历源表并复制内容到嵌套表
            lua_pushnil(L);  // 第一个key
            while (lua_next(L, 3) != 0) {
                if (lua_isinteger(L, -2)) {
                    int key = lua_tointeger(L, -2);
                    if (lua_isinteger(L, -1)) {
                        nested_table->set(key, std::any(lua_tointeger(L, -1)));
                    } else if (lua_isnumber(L, -1)) {
                        nested_table->set(key, std::any(lua_tonumber(L, -1)));
                    } else if (lua_isstring(L, -1)) {
                        nested_table->set(key, std::any(std::string(lua_tostring(L, -1))));
                    } else if (lua_isboolean(L, -1)) {
                        nested_table->set(key, std::any(lua_toboolean(L, -1)));
                    }
                } else if (lua_isstring(L, -2)) {
                    const char* key = lua_tostring(L, -2);
                    if (lua_isinteger(L, -1)) {
                        nested_table->set(key, std::any(lua_tointeger(L, -1)));
                    } else if (lua_isnumber(L, -1)) {
                        nested_table->set(key, std::any(lua_tonumber(L, -1)));
                    } else if (lua_isstring(L, -1)) {
                        nested_table->set(key, std::any(std::string(lua_tostring(L, -1))));
                    } else if (lua_isboolean(L, -1)) {
                        nested_table->set(key, std::any(lua_toboolean(L, -1)));
                    }
                }
                lua_pop(L, 1);  // 移除value，保留key用于下一次迭代
            }
            
            wrapper->set(key, std::any(nested_table));
        }
    // 处理整数键的赋值
    } else if (lua_isinteger(L, 2)) {
        int key = lua_tointeger(L, 2);
        
        if (lua_isnil(L, 3)) {
            wrapper->remove(key);  // 删除指定键
        } else if (lua_isinteger(L, 3)) {
            wrapper->set(key, std::any(lua_tointeger(L, 3)));
        } else if (lua_isnumber(L, 3)) {
            wrapper->set(key, std::any(lua_tonumber(L, 3)));
        } else if (lua_isstring(L, 3)) {
            wrapper->set(key, std::any(std::string(lua_tostring(L, 3))));
        } else if (lua_isboolean(L, 3)) {
            wrapper->set(key, std::any(lua_toboolean(L, 3)));
        } else if (lua_istable(L, 3)) {
            auto nested_table = std::make_shared<LuaTableWrapper>();
            
            lua_pushnil(L);
            while (lua_next(L, 3) != 0) {
                if (lua_isinteger(L, -2)) {
                    int key = lua_tointeger(L, -2);
                    if (lua_isinteger(L, -1)) {
                        nested_table->set(key, std::any(lua_tointeger(L, -1)));
                    } else if (lua_isnumber(L, -1)) {
                        nested_table->set(key, std::any(lua_tonumber(L, -1)));
                    } else if (lua_isstring(L, -1)) {
                        nested_table->set(key, std::any(std::string(lua_tostring(L, -1))));
                    } else if (lua_isboolean(L, -1)) {
                        nested_table->set(key, std::any(lua_toboolean(L, -1)));
                    }
                } else if (lua_isstring(L, -2)) {
                    const char* key = lua_tostring(L, -2);
                    if (lua_isinteger(L, -1)) {
                        nested_table->set(key, std::any(lua_tointeger(L, -1)));
                    } else if (lua_isnumber(L, -1)) {
                        nested_table->set(key, std::any(lua_tonumber(L, -1)));
                    } else if (lua_isstring(L, -1)) {
                        nested_table->set(key, std::any(std::string(lua_tostring(L, -1))));
                    } else if (lua_isboolean(L, -1)) {
                        nested_table->set(key, std::any(lua_toboolean(L, -1)));
                    }
                }
                lua_pop(L, 1);
            }
            
            wrapper->set(key, std::any(nested_table));
        }
    }
    
    return 0;
}

/**
 * @brief Lua元方法__gc实现，处理垃圾回收
 * @param L Lua状态机
 * @return 返回结果数量(0)
 * 
 * 当Lua表被垃圾回收时，自动释放对应的C++对象
 */
int LuaTableWrapper::lua_gc(lua_State* L) {
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    delete wrapper;
    return 0;
}

/**
 * @brief Lua元方法__pairs实现，支持通用遍历
 * @param L Lua状态机
 * @return 返回迭代器函数、表和初始状态(3)
 */
int LuaTableWrapper::lua_pairs(lua_State* L) {
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    
    // 返回next函数、表和nil初始状态
    lua_pushcfunction(L, [](lua_State* L) -> int {
        LuaTableWrapper* wrapper = *(LuaTableWrapper**)lua_touserdata(L, 1);
        size_t index = lua_tointeger(L, 2);
        
        // 处理字符串键
        if (index == 0) {
            auto it = wrapper->string_keys.begin();
            if (it != wrapper->string_keys.end()) {
                lua_pushstring(L, it->first.c_str());
                return 1;
            }
            index = 1;
        }
        
        // 处理整数键
        if (index <= wrapper->int_keys.size()) {
            auto it = wrapper->int_keys.begin();
            std::advance(it, index - 1);
            lua_pushinteger(L, it->first);
            lua_pushinteger(L, index + 1);
            return 2;
        }
        
        return 0;
    });
    
    lua_pushvalue(L, 1); // 表本身
    lua_pushinteger(L, 0); // 初始状态
    return 3;
}

/**
 * @brief Lua元方法__ipairs实现，支持数组遍历
 * @param L Lua状态机
 * @return 返回迭代器函数、表和初始状态(3)
 */
int LuaTableWrapper::lua_ipairs(lua_State* L) {
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    
    // 返回ipairs迭代器
    lua_pushcfunction(L, [](lua_State* L) -> int {
        LuaTableWrapper* wrapper = *(LuaTableWrapper**)lua_touserdata(L, 1);
        int index = lua_tointeger(L, 2);
        
        auto it = wrapper->int_keys.find(index);
        if (it != wrapper->int_keys.end()) {
            lua_pushinteger(L, index);
            lua_pushinteger(L, index + 1);
            return 2;
        }
        
        return 0;
    });
    
    lua_pushvalue(L, 1); // 表本身
    lua_pushinteger(L, 1); // 初始索引
    return 3;
}

/**
 * @brief Lua元方法__len实现，支持#操作符
 * @param L Lua状态机
 * @return 返回表长度(1)
 */
int LuaTableWrapper::lua_len(lua_State* L) {
    LuaTableWrapper* wrapper = *(LuaTableWrapper**)luaL_checkudata(L, 1, "LuaTableWrapper");
    
    // 计算最大连续整数键
    int max_len = 0;
    for (const auto& pair : wrapper->int_keys) {
        if (pair.first > 0 && pair.first == max_len + 1) {
            max_len = pair.first;
        }
    }
    
    lua_pushinteger(L, max_len);
    return 1;
}

void LuaTableWrapper::register_class(lua_State* L) {
    luaL_Reg methods[] = {
        {"__index", lua_index},
        {"__newindex", lua_newindex},
        {"__gc", lua_gc},
        {"__pairs", lua_pairs},
        {"__ipairs", lua_ipairs},
        {"__len", lua_len},
        {"__new", [](lua_State* L) -> int {
            // 支持 t = {} 语法
            LuaTableWrapper* wrapper = new LuaTableWrapper();
            void* ud = lua_newuserdata(L, sizeof(LuaTableWrapper*));
            *(LuaTableWrapper**)ud = wrapper;
            
            luaL_getmetatable(L, "LuaTableWrapper");
            lua_setmetatable(L, -2);
            
            return 1;
        }},
        {NULL, NULL}
    };
    
    luaL_newmetatable(L, "LuaTableWrapper");
    luaL_setfuncs(L, methods, 0);
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    lua_pop(L, 1);
    
    luaL_Reg functions[] = {
        {"new", lua_new},
        {NULL, NULL}
    };
    
    luaL_newlib(L, functions);
    lua_setglobal(L, "LuaTable");
}

void LuaTableWrapper::create_global_table(lua_State* L, const char* name) {
    // 创建新的表实例
    void* ud = lua_newuserdata(L, sizeof(LuaTableWrapper*));
    LuaTableWrapper** wrapper = new (ud) LuaTableWrapper*;
    *wrapper = new LuaTableWrapper();
    
    // 设置元表
    luaL_getmetatable(L, "LuaTableWrapper");
    lua_setmetatable(L, -2);
    
    // 设置为全局变量
    lua_setglobal(L, name);
}

// LActor命名空间实现
namespace LActor {
    int getActorTableVar(lua_State* L) {
        // 获取actor参数
        luaL_checkany(L, 1); // 检查是否有参数
        
        // 创建新的表实例
        void* ud = lua_newuserdata(L, sizeof(LuaTableWrapper*));
        LuaTableWrapper** wrapper = new (ud) LuaTableWrapper*;
        *wrapper = new LuaTableWrapper();
        
        // 设置元表
        luaL_getmetatable(L, "LuaTableWrapper");
        lua_setmetatable(L, -2);
        
        return 1;
    }
    
    void register_namespace(lua_State* L) {
        luaL_Reg functions[] = {
            {"getActorTableVar", getActorTableVar},
            {NULL, NULL}
        };
        
        // 创建LActor表
        luaL_newlib(L, functions);
        lua_setglobal(L, "LActor");
    }
}